# SPDX-License-Identifier: MIT

name: Lint & Test

on:
  push:
    branches:
      - 'master'
      - 'v[0-9]+.[0-9]+.x'  # matches to backport branches, e.g. v3.6.x
      - 'run-ci/*'
    tags:
  pull_request:
  merge_group:
    types: [checks_requested]

permissions:
  read-all

concurrency:
  group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
  cancel-in-progress: true

defaults:
  run:
    shell: bash

jobs:
  lint:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v3

    - name: Run pre-commit
      id: pre-commit
      uses: pre-commit/action@v3.0.0

  docs:
    # unlike the other workflows, we are using version 20.04 here as
    # readthedocs uses 20.04 for building our docs, and we want to be explicit
    runs-on: ubuntu-20.04
    steps:
    - uses: actions/checkout@v3

    - name: Set up environment
      uses: ./.github/actions/setup-env
      with:
        python-version: 3.8

    - name: Run sphinx-build
      run: nox -s docs -- --keep-going -W -w $GITHUB_STEP_SUMMARY

  pyright:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
        experimental: [false]
      fail-fast: false
    continue-on-error: ${{ matrix.experimental }}

    steps:
    - uses: actions/checkout@v3

    - name: Set up environment
      id: setup-env
      uses: ./.github/actions/setup-env
      env:
        PDM_USE_VENV: true
        PDM_VENV_IN_PROJECT: true
      with:
        python-version: ${{ matrix.python-version }}

    - name: Install dependencies
      run: pdm install -d -Gspeed -Gdocs -Gvoice

    - name: Add .venv/bin to PATH
      run: dirname "$(pdm info --python)" >> $GITHUB_PATH

    - name: Set pyright version
      run: |
        PYRIGHT_VERSION="$(pdm run python -c 'import pyright; print(pyright.__pyright_version__)')"
        echo "PYRIGHT_VERSION=$PYRIGHT_VERSION" >> $GITHUB_ENV

    - name: Run pyright (Linux)
      uses: jakebailey/pyright-action@v1.4.1
      id: pyright-linux
      with:
        version: ${{ env.PYRIGHT_VERSION }}
        python-version: ${{ steps.setup-env.outputs.python-version }}
        python-platform: "Linux"
        no-comments: ${{ matrix.python-version != '3.8' }}  # only add comments for one version
        warnings: true

    - name: Run pyright (Windows)
      uses: jakebailey/pyright-action@v1.4.1
      if: always() && (steps.pyright-linux.outcome == 'success' || steps.pyright-linux.outcome == 'failure')
      with:
        version: ${{ env.PYRIGHT_VERSION }}
        python-version: ${{ steps.setup-env.outputs.python-version }}
        python-platform: "Windows"
        no-comments: true  # only add comments for one platform (see above)
        warnings: true

  misc:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3

    - name: Set up environment
      id: setup
      uses: ./.github/actions/setup-env
      with:
        python-version: 3.8

    - name: Run slotscheck
      if: (success() || failure()) && steps.setup.outcome == 'success'
      run: nox -s slotscheck

    - name: Run check-manifest
      if: (success() || failure()) && steps.setup.outcome == 'success'
      run: nox -s check-manifest

    # This only runs if the previous steps were successful, no point in running it otherwise
    - name: Try building package
      run: |
        pdm install -dG build

        pdm run python -m build
        ls -la dist/

        pdm run twine check --strict dist/*

    # run the libcst parsers and check for changes
    - name: libcst codemod
      run: |
        nox -s codemod -- run-all
        if [ -n "$(git status --porcelain)" ]; then
          echo "::error::Please run 'nox -s codemod -- run-all' locally and commit the changes." >&2;
          echo "::group::git diff"
          git diff
          echo "::endgroup::"
          exit 1;
        else
          exit 0;
        fi

  pytest:
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
        os: ["windows-latest", "ubuntu-latest", "macos-latest"]
        experimental: [false]
      fail-fast: true
    continue-on-error: ${{ matrix.experimental }}

    env:
      GITHUB_STEP_SUMMARY_HEADER: "<details><summary>#name#</summary>\n<pre>"
      GITHUB_STEP_SUMMARY_FOOTER: "</pre></details>\n"

    steps:
    - uses: actions/checkout@v3

    - name: Set up environment
      id: setup-env
      uses: ./.github/actions/setup-env
      with:
        python-version: ${{ matrix.python-version }}

    - name: Install dependencies
      run: pdm install -dG test  # needed for coverage

    - name: Test package install
      run: |
        python -m pip install .

    - name: Run pytest
      id: run_tests
      # use non-utc timezone, to test time/date-dependent features properly
      env:
        TZ: "America/New_York"
      run: |
        echo "$GITHUB_STEP_SUMMARY_HEADER" | sed "s/#name#/Test Summary/" >> $GITHUB_STEP_SUMMARY
        nox --force-python ${{ steps.setup-env.outputs.python-version }} -s test -- --color=no --cov-report= | tee -a $GITHUB_STEP_SUMMARY
        echo "$GITHUB_STEP_SUMMARY_FOOTER" >> $GITHUB_STEP_SUMMARY

    - name: Print Coverage Output
      if: always() && (steps.run_tests.outcome == 'success' || steps.run_tests.outcome == 'failure')
      run: |
        echo "$GITHUB_STEP_SUMMARY_HEADER" | sed "s/#name#/Coverage Summary/" >> $GITHUB_STEP_SUMMARY
        pdm run coverage report | tee -a $GITHUB_STEP_SUMMARY
        echo "$GITHUB_STEP_SUMMARY_FOOTER" >> $GITHUB_STEP_SUMMARY

  # thanks to aiohttp for this part of the workflow
  check:  # This job does nothing and is only used for the branch protection
    if: always()
    needs:
    - lint
    - docs
    - pyright
    - misc
    - pytest

    runs-on: ubuntu-latest

    steps:
    - name: Decide whether the needed jobs succeeded or failed
      uses: re-actors/alls-green@v1.2.2
      with:
        jobs: ${{ toJSON(needs) }}
